// 删除二叉搜索树中的节点
// 给定一个二叉搜索树的根节点 root 和一个值 key，删除二叉搜索树中的 key 对应的节点，并保证二叉搜索树的性质不变。返回二叉搜索树（有可能被更新）的根节点的引用。

// 一般来说，删除节点可分为两个步骤：
// 首先找到需要删除的节点；
// 如果找到了，删除它。
// 说明： 要求算法时间复杂度为 O(h)，h 为树的高度。

// 示例:
// root = [5,3,6,2,4,null,7]
// key = 3
//     5
//    / \
//   3   6
//  / \   \
// 2   4   7
// 给定需要删除的节点值是 3，所以我们首先找到 3 这个节点，然后删除它。

// 一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。-- 取右子树的最小值

//     5
//    / \
//   4   6
//  /     \
// 2       7

// 另一个正确答案是 [5,2,6,null,4,null,7]。 -- 取左子树的最大值

//     5
//    / \
//   2   6
//    \   \
//     4   7



// ==================================递归解法=================================
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */

/**
 * @param {TreeNode} node
 * @return {TreeNode}
 */
var getMin = function (node) {
  let p = node.right;
  while(p.left) {
      p = p.left;
  }
  return p;
}
/**
* @param {TreeNode} root
* @param {number} key
* @return {TreeNode}
*/
// 递归定义：给定根节点root与要删除的节点的值为val，返回更新后的root
var deleteNode = function(root, key) {
  if(!root) return null;
  if(root.val === key) {
      // 找到了需要删除的元素
      // 1. 若该节点是叶子节点，直接删除，返回空节点
      if(!root.left && !root.right) {
          return null;
      }
      // 2.该节点仅有左子树，或仅有右子树
      if(root.left && !root.right) {
          return root.left;
      }
      if(!root.left && root.right) {
          return root.right;
      }
      // 该节点既有左子树，又有右子树
      // 获得该节点的左子树的最大值或右子树的最小值，代替该节点，再删除那个最大值或最小值节点
      if(root.left && root.right) {
          let minVal = getMin(root).val;
          root.val = minVal;
          root.right = deleteNode(root.right, minVal);
      }
  }
  else if(root.val < key) {
      // 节点的右子树需要被改动，右节点等于更新后的右子树
      root.right = deleteNode(root.right, key);
  }
  else if(root.val > key) {
      // 节点的左子树需要被改动，左节点等于更新后的左子树
      root.left = deleteNode(root.left, key);
  }
  // 返回更新后的子树
  return root;
};

//  ==================================递归加迭代=================================
// 不返回更新后的根节点，类式写法见./树/BST.js